import CryptoJS from 'crypto-js'
import { h } from 'vue'

export function isExternal(path: string) {
  return /^(https?:|mailto:|tel:)/.test(path)
}

export function uuid() {
  const s: Array<any> = []
  const hexDigits = '0123456789abcdef'
  for (let i = 0; i < 36; i++) {
    s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1)
  }
  s[14] = '4' // bits 12-15 of the time_hi_and_version field to 0010
  s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1) // bits 6-7 of the clock_seq_hi_and_reserved to 01
  s[8] = s[13] = s[18] = s[23] = '-'
  const uuid = s.join('')
  return uuid
}

export function randomString(length: number) {
  const str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
  let result = ''
  for (let i = length; i > 0; --i) {
    result += str[Math.floor(Math.random() * str.length)]
  }
  return result
}

/**
 * 中划线字符驼峰
 * @param {*} str 要转换的字符串
 * @returns 返回值
 */
export function toHump(str: string): string {
  if (!str) return str
  return str
    .replace(/\-(\w)/g, function (all, letter) {
      return letter.toUpperCase()
    })
    .replace(/(\s|^)[a-z]/g, function (char) {
      return char.toUpperCase()
    })
}

export function sortColumns(originColumns: any[], newColumns: any[]) {
  if (!originColumns || !newColumns) {
    return
  }
  if (newColumns.length === 0) {
    originColumns.length = 0
  } else {
    const selectionItem = originColumns.find((it) => it.type === 'selection')
    originColumns.length = 0
    if (selectionItem) {
      originColumns.push(selectionItem)
    }
    originColumns.push(...newColumns)
  }
}

export function getNowDate() {
  const date = new Date()
  const sign2 = ':'
  const year = date.getFullYear() // 年
  let month: string | number = date.getMonth() + 1 // 月
  let day: string | number = date.getDate() // 日
  let hour: string | number = date.getHours() // 时
  let minutes: string | number = date.getMinutes() // 分
  let seconds: string | number = date.getSeconds() //秒
  const weekArr = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期天']
  const week = weekArr[date.getDay()]
  // 给一位数的数据前面加 “0”
  if (month >= 1 && month <= 9) {
    month = '0' + month
  }
  if (day >= 0 && day <= 9) {
    day = '0' + day
  }
  if (hour >= 0 && hour <= 9) {
    hour = '0' + hour
  }
  if (minutes >= 0 && minutes <= 9) {
    minutes = '0' + minutes
  }
  if (seconds >= 0 && seconds <= 9) {
    seconds = '0' + seconds
  }
  return [year + '-' + month + '-' + day, hour + sign2 + minutes + sign2 + seconds, week]
}

// 判断是否录入
// 0 被认为是有效输入 '' 被认为是无效输入
export function isValid(val: any) {
  return !!val || (typeof val == 'number' && val === 0)
}

// 工具函数 内容增加 unit 单位 默认 “元”
export function unitVal(val: any, unit: any = '元') {
  if (val || val === 0) {
    return val + ' ' + unit
  } else {
    return '-'
  }
}

/**
 * 将数值格式化为字符串，可选择是否添加千分位分隔符
 * @param val 待格式化的数值，可以是任何类型，但只有数值类型会被格式化
 * @param thousandth 是否添加千分位分隔符，默认为 true
 * @returns 格式化后的字符串
 */
export function formatNumber(val: any, thousandth = false) {
  let formatedStr = ''
  // 传入 null 或 undefined 时，返回 '0'
  if (val === null || val === undefined) {
    formatedStr = '0'
  }
  // 当传入的值为有效数值时，进行格式化
  if (isValid(val)) {
    // 将数值格式化为保留两位小数的字符串
    const number = val.toFixed(2)
    // 根据 thousandth 参数决定是否添加千分位分隔符
    if (thousandth) {
      // 添加千分位分隔符
      formatedStr = String(number).replace(/\B(?=(\d{3})+(?!\d))/g, ',')
    } else {
      // 不添加千分位分隔符
      formatedStr = String(number)
    }
  }

  return formatedStr
}

// 小数求和
export function decimalAddition(x = 0, y = 0) {
  const sum = (x + y).toFixed(3)
  return Math.round(+sum * 100) / 100
}
// 小数求差
export function decimalSubtract(x = 0, y = 0) {
  const sum = (x - y).toFixed(3)
  return Math.round(+sum * 100) / 100
}

const KEY = CryptoJS.enc.Utf8.parse('d7b85f6e214abcde')

// 加密
export const AES_Encrypt = (plaintext: any) => {
  const ciphertext = CryptoJS.AES.encrypt(plaintext, KEY, {
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.Pkcs7,
  }).toString()
  return ciphertext
}
// 解密
export const AES_Decrypt = (jsonStr: any) => {
  const plaintext = CryptoJS.AES.decrypt(jsonStr, KEY, {
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.Pkcs7,
  }).toString(CryptoJS.enc.Utf8)

  return plaintext
}
/**
 * h('span', [h('span', '请先上传合同模板名称租车合同模板的'), h('span', { style: { color: 'red' } }, '公司印章'), h('span', '，再生成电子合同')])
 * => <span>
 *      <span>请先上传合同模板名称租车合同模板的</span>
 *      <span style={color: 'red'}>公司印章</span>
 *      <span>，再生成电子合同</span>
 *    </span>
 */
// 指定字符串变色
export function targetStrColor(str: string, target: string, styles: any): any {
  const arr = str.split(target)
  return h(
    'span',
    arr.map((item, index) => (index === arr.length - 1 ? item : [item, h('span', { style: styles }, target)]))
  )
}
/**
 * 编码参数以便URL传输。
 *
 * 该函数将任意类型的值编码为URL兼容的格式。
 * 特别地，它会将数组类型转换为JSON字符串后再进行编码，以确保数组结构在传输过程中保持不变。
 *
 * @param value - 需要编码的任意类型的值。这可以是字符串、数字、数组等。
 * @returns 返回输入值的URL编码字符串表示。
 */
function encodeParam(value: any) {
  if (Array.isArray(value)) {
    // 将数组转换为JSON字符串并进行URL编码
    return JSON.stringify(value)
  }
  // 直接对非数组值进行URL编码
  return value
}
/**
 * 将一个对象的属性转换为查询参数字符串
 *
 * 此函数遍历给定对象的所有可枚举属性，将它们转换为URL查询参数的形式
 * 如果属性值未定义，则该属性不会被包含在返回的查询字符串中
 *
 * @param obj 要转换为查询参数的对象
 * @param targetArray 可选的数组，转换后的查询参数将被添加到这个数组中如果未提供，则创建一个新的数组
 * @returns 返回组装好的查询字符串如果没有任何查询参数，则返回空字符串
 */
export function setQueryParams(obj: any, targetArray?: any) {
  // 初始化查询参数数组，如果提供了targetArray，则使用它，否则创建一个新的数组
  const params = targetArray || []

  // 遍历对象的所有可枚举属性
  for (const key in obj) {
    // 检查对象是否拥有该属性且属性值不是undefined
    if (obj.hasOwnProperty(key) && obj[key] !== undefined) {
      // 将属性转换为查询参数的形式，并添加到params数组中
      params.push(`${key}=${encodeParam(obj[key])}`)
    }
  }

  // 根据params数组的长度决定返回的查询字符串如果数组为空，则返回空字符串
  return params.length > 0 ? `?${params.join('&')}` : ''
}
/**
 * 获取URL参数
 * @param value
 * @returns
 */
export function evalQueryParam(value: string) {
  if (!value) {
    console.warn('Input value is empty or null')
    return null
  }

  try {
    const decodeValue = decodeURIComponent(value)
    return JSON.parse(decodeValue)
  } catch (error) {
    if (error instanceof URIError) {
      console.error('Invalid URI encoding:', error)
    } else if (error instanceof SyntaxError) {
      console.error('Invalid JSON format:', error)
    } else {
      console.error('Unexpected error:', error)
    }
    return null
  }
}
